package cn.demoncat.util.lang;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

/**
 * Optional对象处理（空处理）
 * 
 * @author 延晓磊
 *
 * @since 2018年7月7日
 */
public class OptionalUtil {

	private static final Logger LOG = LoggerFactory.getLogger(OptionalUtil.class);
	
	/**
	 * Optional Get
	 * 
	 * Spring Data 2.0 返回 Optional<T> 而非 T，需要通过get()获取，但在T为null时会抛异常
	 * 
	 * 本方法用于折衷Optional.get()来获取T，如果T为null则返回null而不抛异常
	 * 
	 * @param op
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2018年7月7日
	 */
	public static <T>T get(Optional<T> op) {
		return op.orElse(null);
	}
	
	/**
	 * 获取数据，抛异常时返回null
	 * 
	 * @param supplier
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月11日
	 */
	public static <T>T get(Supplier<T> supplier){
		try {
			return supplier.get();
		} catch (Exception e) {
			LOG.warn("数据获取异常被忽略，返回为null" , e);
			return null;
		}
	}
	
	/**
	 * 如果o为空，返回null；如果非空，执行fn()
	 * 
	 * @param o		对象
	 * @param fn	如果o非null执行fn.get()
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, Supplier<R> fn){
		if (o == null) {
			return null;
		}else {
			return fn.get();
		}
	}

	/**
	 * 如果o为空，返回null；如果非空，执行fn(o)
	 * 
	 * @param o		对象
	 * @param fn	如果o非null执行fn.apply(o)
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, Function<T,R> fn){
		if (o == null) {
			return null;
		}else {
			return fn.apply(o);
		}
	}

	/**
	 * 如果o非空，执行fn(o)
	 *
	 * @param o		对象
	 * @param fn	如果o非null执行fn.accept(o)
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T>void consumer(T o, Consumer<T> fn){
		if (o != null) {
			fn.accept(o);
		}
	}

	/**
	 * 如果o为空，nullFn；如果非空，执行notNullFn
	 *
	 * @param o		对象
	 * @param nullFn	为空时执行
	 * @param notNullFn	非空时执行
	 * @return
	 *
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T>void consumer(T o, Runnable nullFn, Consumer<T> notNullFn){
		if (o == null) {
			nullFn.run();
		}else{
			notNullFn.accept(o);
		}
	}
	
	/**
	 * 如果o为空，返回def；如果非空，返回res
	 * 
	 * @param o		对象
	 * @param def	默认值
	 * @param res	结果值
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, R def, R res){
		if (o == null) {
			return def;
		}else {
			return res;
		}
	}
	
	/**
	 * 如果o为空，返回def；如果非空，执行fn()
	 * 
	 * @param o		对象
	 * @param def	默认值
	 * @param fn	如果o非null行fn.get()
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, R def, Supplier<R> fn){
		if (o == null) {
			return def;
		}else {
			return fn.get();
		}
	}
	
	/**
	 * 如果o为空，返回def；如果非空，执行fn(o)
	 * 
	 * @param o		对象
	 * @param def	默认值
	 * @param fn	如果o非null行fn.apply(o)
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, R def, Function<T,R> fn){
		if (o == null) {
			return def;
		}else {
			return fn.apply(o);
		}
	}
	
	/**
	 * 如果o为空，执行fn1()；如果非空，执行fn2()
	 * 
	 * @param o		对象
	 * @param fn1	如果o为null执行fn1.get()
	 * @param fn2	如果o非null行fn2.get()
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, Supplier<R> fn1, Supplier<R> fn2){
		if (o == null) {
			return fn1.get();
		}else {
			return fn2.get();
		}
	}

	/**
	 * 如果o为空，执行fn1()；如果非空，执行fn2(o)
	 * 
	 * @param o		对象
	 * @param fn1	如果o为null执行fn1.get()
	 * @param fn2	如果o非null行fn2.apply(o)
	 * @return
	 * 
	 * @author 延晓磊
	 *
	 * @since 2020年3月18日
	 */
	public static <T,R>R get(T o, Supplier<R> fn1, Function<T,R> fn2){
		if (o == null) {
			return fn1.get();
		}else {
			return fn2.apply(o);
		}
	}
}
